<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="TLDW Server API Testing Interface - Verify API functionality and test endpoints">
    <title>TLDW API Testing Interface</title>

    <!-- External CSS -->
    <link rel="stylesheet" href="css/styles.css">
    <script defer src="js/setup-guard.js"></script>
    <!-- Inline handler shim removed after migrating handlers to modules -->

    <!-- Additional styles for JSON syntax highlighting -->
    <style>
        .json-key { color: #a31515; }
        .json-string { color: #0451a5; }
        .json-number { color: #098658; }
        .json-boolean { color: #0000ff; }
        .json-null { color: #808080; }

        /* Modal styles */
        .modal-backdrop {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 999;
            animation: fadeIn 0.2s ease;
        }

        .modal {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: var(--color-surface);
            border-radius: var(--radius-lg);
            box-shadow: var(--shadow-xl);
            z-index: 1000;
            max-height: 90vh;
            overflow-y: auto;
            animation: slideUp 0.3s ease;
        }

        .modal-small { width: 400px; }
        .modal-medium { width: 600px; }
        .modal-large { width: 900px; }
        .modal-full { width: 95%; height: 95vh; }

        .modal-header {
            padding: var(--spacing-lg);
            border-bottom: 1px solid var(--color-border);
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .modal-title {
            font-size: 1.25rem;
            font-weight: 600;
            margin: 0;
        }

        .modal-close {
            background: none;
            border: none;
            font-size: 1.5rem;
            cursor: pointer;
            color: var(--color-text-muted);
            padding: 0;
            width: 32px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: var(--radius-md);
            transition: var(--transition-fast);
        }

        .modal-close:hover {
            background: var(--color-surface-alt);
            color: var(--color-text);
        }

        .modal-body {
            padding: var(--spacing-lg);
        }

        .modal-footer {
            padding: var(--spacing-lg);
            border-top: 1px solid var(--color-border);
            display: flex;
            justify-content: flex-end;
            gap: var(--spacing-md);
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        @keyframes slideUp {
            from {
                transform: translate(-50%, -40%);
                opacity: 0;
            }
            to {
                transform: translate(-50%, -50%);
                opacity: 1;
            }
        }

        @keyframes slideOut {
            from {
                transform: translateX(0);
                opacity: 1;
            }
            to {
                transform: translateX(100%);
                opacity: 0;
            }
        }

        /* Loading content styles */
        .loading-content {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: var(--spacing-md);
        }

        .loading-message {
            color: var(--color-text-secondary);
            font-size: 0.9rem;
        }

        /* History item styles */
        .history-list {
            max-height: 60vh;
            overflow-y: auto;
        }

        .history-item {
            padding: var(--spacing-md);
            border: 1px solid var(--color-border);
            border-radius: var(--radius-md);
            margin-bottom: var(--spacing-md);
            transition: var(--transition-fast);
        }

        .history-item:hover {
            box-shadow: var(--shadow-sm);
        }

        .history-item.success {
            border-left: 3px solid var(--color-success);
        }

        .history-item.error {
            border-left: 3px solid var(--color-error);
        }

        .history-item-header {
            display: flex;
            align-items: center;
            gap: var(--spacing-md);
            margin-bottom: var(--spacing-sm);
        }

        .history-path {
            font-family: var(--font-family-mono);
            font-size: 0.9rem;
            color: var(--color-text-secondary);
            flex: 1;
        }

        .history-status {
            font-weight: 600;
        }

        .history-item-details {
            display: flex;
            gap: var(--spacing-lg);
            font-size: 0.85rem;
            color: var(--color-text-muted);
        }

        .history-error {
            margin-top: var(--spacing-sm);
            padding: var(--spacing-sm);
            background: var(--color-surface-alt);
            border-radius: var(--radius-sm);
            color: var(--color-error);
            font-size: 0.85rem;
        }

        /* JSON Viewer styles */
        .json-viewer {
            font-family: var(--font-family-mono);
            font-size: 0.9rem;
            line-height: 1.5;
        }

        .json-viewer-toolbar {
            display: flex;
            gap: var(--spacing-sm);
            margin-bottom: var(--spacing-md);
            padding-bottom: var(--spacing-md);
            border-bottom: 1px solid var(--color-border);
        }

        .json-viewer-content {
            background: var(--color-surface-alt);
            padding: var(--spacing-md);
            border-radius: var(--radius-md);
            overflow-x: auto;
        }

        /* Simple badge */
        .badge {
            background: var(--color-surface-alt);
            border: 1px solid var(--color-border);
            border-radius: var(--radius-pill);
            padding: 2px 8px;
            font-size: 0.8rem;
            margin-left: 8px;
        }
        .badge.badge-warn { background: #fff7e6; border-color: #ffe0a3; }
        .badge.badge-crit { background: #ffe6e6; border-color: #ffb3b3; }

        .json-toggle {
            cursor: pointer;
            user-select: none;
            display: inline-block;
            width: 1em;
            text-align: center;
            color: var(--color-text-muted);
            transition: var(--transition-fast);
        }

        .json-toggle:hover {
            color: var(--color-primary);
        }

        .json-toggle.collapsed {
            transform: rotate(-90deg);
        }

        .json-content {
            padding-left: var(--spacing-lg);
        }

        .json-item {
            margin: 2px 0;
        }

        .json-bracket,
        .json-comma,
        .json-colon {
            color: var(--color-text-secondary);
        }

        /* Drag over styles */
        .drag-over {
            background: var(--color-primary-light) !important;
            border-color: var(--color-primary) !important;
        }

        /* Search box */
        .search-container {
            position: fixed;
            top: var(--spacing-lg);
            right: var(--spacing-lg);
            z-index: 95;
            display: none;
        }

        .search-container.visible {
            display: block;
        }

        #endpoint-search {
            width: 300px;
            padding: var(--spacing-sm) var(--spacing-md);
            border-radius: var(--radius-pill);
            border: 1px solid var(--color-border);
            background: var(--color-surface);
            color: var(--color-text);
        }

        #no-search-results {
            text-align: center;
            padding: var(--spacing-xl);
            color: var(--color-text-muted);
            display: none;
        }
    </style>
</head>
<body>
    <!-- Skip to main content link for accessibility -->
    <a href="#main-content-area" class="skip-link">Skip to main content</a>

    <div class="app-container">
        <header>
            <h1>TLDW API Testing Interface</h1>
            <div class="header-controls">
                <div class="api-status" aria-live="polite">
                    <span class="status-dot" aria-hidden="true"></span>
                    <span class="api-status-text">Checking...</span>
                </div>
                <span id="dlq-badge" class="badge" title="Total DLQ depth">DLQ: 0</span>
                <a href="/setup" class="badge" title="Open Setup Wizard" style="text-decoration:none;">Setup</a>
                <!-- Correlation badges are force-hidden by default to avoid UI clutter. -->
                <span id="reqid-badge" class="badge" title="Last X-Request-ID" style="display:none; visibility:hidden;">RID: -</span>
                <span id="trace-badge" class="badge" title="Last traceparent/X-Trace-Id" style="display:none; visibility:hidden;">Trace: -</span>
                <label id="advanced-toggle-wrapper" class="badge" style="cursor:pointer; user-select:none;">
                    <input type="checkbox" id="toggle-advanced" style="margin-right:6px; vertical-align:middle;">
                    <span id="advanced-toggle-label" style="vertical-align:middle;">Show Advanced Panels</span>
                </label>
                <button id="theme-toggle" class="theme-toggle" aria-label="Toggle theme">
                    🌙
                </button>
            </div>
        </header>

        <!-- Search Container -->
        <div class="search-container">
            <div style="display:flex; gap:8px; align-items:center;">
                <input
                    type="search"
                    id="endpoint-search"
                    placeholder="Search endpoints... (Ctrl+K)"
                    aria-label="Search endpoints"
                >
                <button id="preload-endpoints-btn" class="btn btn-secondary btn-sm" title="Load all tabs so search spans every endpoint">Load all endpoints for search</button>
            </div>
        </div>

        <!-- Top Level Tabs -->
        <nav class="top-tab-container" role="navigation" aria-label="Main navigation">
            <!-- Row 1: Core Features -->
            <div class="top-tab-buttons top-tab-row" role="tablist">
                <button class="top-tab-button" data-toptab="simple" id="top-tab-simple" role="tab" aria-selected="false">
                    Simple
                </button>
                <button class="top-tab-button" data-toptab="general" role="tab" aria-selected="false">
                    General
                </button>
                <button class="top-tab-button" data-toptab="auth" role="tab" aria-selected="false">
                    Auth
                </button>
                <button class="top-tab-button" data-toptab="media" role="tab" aria-selected="false">
                    Media
                </button>
                <button class="top-tab-button" data-toptab="chat" id="top-tab-chat" role="tab" aria-selected="false">
                    Chat
                </button>
                <button class="top-tab-button" data-toptab="prompts" role="tab" aria-selected="false">
                    Prompts
                </button>
                <button class="top-tab-button" data-toptab="notes" role="tab" aria-selected="false">
                    Notes
                </button>
                <button class="top-tab-button" data-toptab="flashcards" role="tab" aria-selected="false">
                    Flashcards
                </button>
                <button class="top-tab-button" data-toptab="watchlists" role="tab" aria-selected="false">
                    Watchlists
                </button>
                <button class="top-tab-button" data-toptab="rag" role="tab" aria-selected="false">
                    RAG
                </button>
                <button class="top-tab-button" data-toptab="workflows" role="tab" aria-selected="false">
                    Workflows
                </button>
                <button class="top-tab-button" data-toptab="keywords" role="tab" aria-selected="false">
                    Keywords
                </button>
                <button class="top-tab-button" data-toptab="embeddings" role="tab" aria-selected="false">
                    Embeddings
                </button>
            </div>

            <!-- Row 2: Processing & Analysis -->
            <div class="top-tab-buttons top-tab-row" role="tablist">
                <button class="top-tab-button" data-toptab="webscraping" role="tab" aria-selected="false">
                    Web Scraping
                </button>
                <button class="top-tab-button" data-toptab="audio" role="tab" aria-selected="false">
                    Audio
                </button>
                <button class="top-tab-button" data-toptab="research" role="tab" aria-selected="false">
                    Research
                </button>
                <button class="top-tab-button" data-toptab="chatbooks" role="tab" aria-selected="false">
                    Chatbooks
                </button>
                <button class="top-tab-button" data-toptab="mcp" role="tab" aria-selected="false">
                    MCP
                </button>
                <button class="top-tab-button" data-toptab="llamacpp" role="tab" aria-selected="false">
                    LLM Inference
                </button>
                <button class="top-tab-button" data-toptab="evaluations" role="tab" aria-selected="false">
                    Evaluations
                </button>
                <button class="top-tab-button" data-toptab="persona" role="tab" aria-selected="false">
                    Persona
                </button>
            </div>

            <!-- Row 3: Administration & System -->
            <div class="top-tab-buttons top-tab-row" role="tablist">
                <button class="top-tab-button" data-toptab="admin" role="tab" aria-selected="false">
                    Admin
                </button>
                <button class="top-tab-button" data-toptab="config" role="tab" aria-selected="false">
                    Config
                </button>
                <button class="top-tab-button" data-toptab="llm" role="tab" aria-selected="false">
                    LLM
                </button>
                <button class="top-tab-button" data-toptab="health" role="tab" aria-selected="false">
                    Health
                </button>
                <button class="top-tab-button" data-toptab="sync" role="tab" aria-selected="false">
                    Sync
                </button>
                <button class="top-tab-button" data-toptab="maintenance" role="tab" aria-selected="false">
                    Maintenance
                </button>
                <button class="top-tab-button" data-toptab="personalization" role="tab" aria-selected="false">
                    Personalization
                </button>
            </div>
        </nav>

        <div id="simple-subtabs" class="sub-tab-row" role="navigation" aria-label="Simple sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabSimpleLanding" role="tab">
                    Quick Actions
                </button>
            </div>
        </div>

        <!-- Sub Level Tab Rows -->
        <div id="flashcards-subtabs" class="sub-tab-row" role="navigation" aria-label="Flashcards sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabFlashcardsManage" data-load-group="flashcards" role="tab">
                    Manage
                </button>
                <button class="sub-tab-button" data-content-id="tabFlashcardsReview" data-load-group="flashcards" role="tab">
                    Review
                </button>
                <button class="sub-tab-button" data-content-id="tabFlashcardsImport" data-load-group="flashcards" role="tab">
                    Import/Export
                </button>
            </div>
        </div>
        <div id="general-subtabs" class="sub-tab-row" role="navigation" aria-label="General sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabGlobalSettings" role="tab">
                    Global Settings
                </button>
                <button class="sub-tab-button" data-content-id="tabDebug" data-load-group="general" role="tab">
                    Debug
                </button>
                <button class="sub-tab-button" data-content-id="tabHistory" role="tab">
                    Request History
                </button>
            </div>
        </div>

        <div id="auth-subtabs" class="sub-tab-row" role="navigation" aria-label="Auth sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabAuth" data-load-group="auth" role="tab">
                    Basic
                </button>
                <button class="sub-tab-button" data-content-id="tabAuthSecurity" data-load-group="auth" role="tab">
                    Security
                </button>
                <button class="sub-tab-button" data-content-id="tabAuthApiKeys" data-load-group="auth" role="tab">
                    My API Keys
                </button>
                <button class="sub-tab-button" data-content-id="tabAuthMfa" data-load-group="auth" role="tab">
                    MFA
                </button>
                <button class="sub-tab-button" data-content-id="tabAuthVirtualKey" data-load-group="auth" role="tab">
                    Virtual Key
                </button>
                <button class="sub-tab-button" data-content-id="tabAuthPermissionsMatrix" data-load-group="auth" role="tab">
                    Permissions Matrix
                </button>
            </div>
        </div>

        <div id="media-subtabs" class="sub-tab-row" role="navigation" aria-label="Media sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabMediaManagement" data-load-group="media" role="tab">
                    Media Management
                </button>
                <button class="sub-tab-button" data-content-id="tabMultiItemAnalysis" data-load-group="media" role="tab">
                    Multi-Item Analysis
                </button>
                <button class="sub-tab-button" data-content-id="tabMediaVersioning" data-load-group="media" role="tab">
                    Versioning
                </button>
                <button class="sub-tab-button" data-content-id="tabMediaIngestionPersistence" data-load-group="media" role="tab">
                    Ingestion (DB)
                </button>
                <button class="sub-tab-button" data-content-id="tabMediaProcessingNoDB" data-load-group="media" role="tab">
                    Processing (No DB)
                </button>
                <button class="sub-tab-button" data-content-id="tabWebScraping" data-load-group="media" role="tab">
                    Web Scraping
                </button>
                <button class="sub-tab-button" data-content-id="tabMediaAnalysis" data-load-group="media" role="tab">
                    Analysis
                </button>
            </div>
        </div>

        <div id="chat-subtabs" class="sub-tab-row" role="navigation" aria-label="Chat sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabChatCompletions" data-load-group="chat" role="tab">
                    Chat Completions
                </button>
                <button class="sub-tab-button" data-content-id="tabCharacters" data-load-group="chat" role="tab">
                    Characters
                </button>
                <button class="sub-tab-button" data-content-id="tabConversations" data-load-group="chat" role="tab">
                    Conversations
                </button>
                <button class="sub-tab-button" data-content-id="tabDictionaries" data-load-group="chat" role="tab">
                    Dictionaries
                </button>
            </div>
        </div>

        <div id="chatbooks-subtabs" class="sub-tab-row" role="navigation" aria-label="Chatbooks sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabChatbooksExport" data-load-group="chatbooks" role="tab">
                    Export/Import
                </button>
                <button class="sub-tab-button" data-content-id="tabChatbooksJobs" data-load-group="chatbooks" role="tab">
                    Jobs
                </button>
            </div>
        </div>

        <div id="rag-subtabs" class="sub-tab-row" role="navigation" aria-label="RAG sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabRAGSearch" data-load-group="rag" role="tab">
                    Search
                </button>
                <button class="sub-tab-button" data-content-id="tabRAGEmbeddings" data-load-group="rag" role="tab">
                    Embeddings
                </button>
            </div>
        </div>

        <div id="workflows-subtabs" class="sub-tab-row" role="navigation" aria-label="Workflows sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabWorkflowsDefinitions" data-load-group="workflows" role="tab">
                    Definitions
                </button>
                <button class="sub-tab-button" data-content-id="tabWorkflowsRuns" data-load-group="workflows" role="tab">
                    Runs
                </button>
                <button class="sub-tab-button" data-content-id="tabWorkflowsApprovals" data-load-group="workflows" role="tab">
                    Approvals
                </button>
            </div>
        </div>

        <div id="prompts-subtabs" class="sub-tab-row" role="navigation" aria-label="Prompts sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabPromptsList" data-load-group="prompts" role="tab">
                    List Prompts
                </button>
                <button class="sub-tab-button" data-content-id="tabPromptsManage" data-load-group="prompts" role="tab">
                    Manage
                </button>
            </div>
        </div>

        <div id="notes-subtabs" class="sub-tab-row" role="navigation" aria-label="Notes sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabNotesList" data-load-group="notes" role="tab">
                    List Notes
                </button>
                <button class="sub-tab-button" data-content-id="tabNotesManage" data-load-group="notes" role="tab">
                    Manage
                </button>
                <button class="sub-tab-button" data-content-id="tabNotesKeywords" data-load-group="notes" role="tab">
                    Keywords
                </button>
            </div>
        </div>

        <div id="watchlists-subtabs" class="sub-tab-row" role="navigation" aria-label="Watchlists sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabWatchlistsItems" data-load-group="watchlists" role="tab">
                    Items
                </button>
                <button class="sub-tab-button" data-content-id="tabWatchlistsOutputs" data-load-group="watchlists" role="tab">
                    Outputs
                </button>
                <button class="sub-tab-button" data-content-id="tabWatchlistsRuns" data-load-group="watchlists" role="tab">
                    Runs
                </button>
                <button class="sub-tab-button" data-content-id="tabWatchlistsTemplates" data-load-group="watchlists" role="tab">
                    Templates
                </button>
            </div>
        </div>

        <div id="persona-subtabs" class="sub-tab-row" role="navigation" aria-label="Persona sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabPersona" data-load-group="persona" role="tab">
                    Persona Agent
                </button>
            </div>
        </div>

        <div id="personalization-subtabs" class="sub-tab-row" role="navigation" aria-label="Personalization sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabPersonalization" data-load-group="personalization" role="tab">
                    Dashboard
                </button>
            </div>
        </div>

        <div id="evaluations-subtabs" class="sub-tab-row" role="navigation" aria-label="Evaluations sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabEvalsOpenAI" data-load-group="evaluations" role="tab">
                    OpenAI Format
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsGEval" data-load-group="evaluations" role="tab">
                    G-Eval
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsRAG" data-load-group="evaluations" role="tab">
                    RAG Evaluation
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsRAGPipeline" data-load-group="evaluations" role="tab">
                    RAG Pipeline
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsRAGPresets" data-load-group="evaluations" role="tab">
                    RAG Presets
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsRuns" data-load-group="evaluations" role="tab">
                    Runs
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsResponseQuality" data-load-group="evaluations" role="tab">
                    Response Quality
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsOCR" data-load-group="evaluations" role="tab">
                    OCR Evaluation
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsManagement" data-load-group="evaluations" role="tab">
                    Management
                </button>
                <button class="sub-tab-button" data-content-id="tabEvalsDatasets" data-load-group="evaluations" role="tab">
                    Datasets
                </button>
            </div>
        </div>

        <div id="keywords-subtabs" class="sub-tab-row" role="navigation" aria-label="Keywords sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabKeywordsOverview" data-load-group="keywords" role="tab">
                    Overview
                </button>
                <button class="sub-tab-button" data-content-id="tabKeywordsManage" data-load-group="keywords" role="tab">
                    Manage Keywords
                </button>
                <button class="sub-tab-button" data-content-id="tabKeywordsSync" data-load-group="keywords" role="tab">
                    Sync & Migrate
                </button>
                <button class="sub-tab-button" data-content-id="tabKeywordsAnalytics" data-load-group="keywords" role="tab">
                    Analytics
                </button>
            </div>
        </div>

        <div id="embeddings-subtabs" class="sub-tab-row" role="navigation" aria-label="Embeddings sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabEmbeddingsCreate" data-load-group="embeddings" role="tab">
                    Create Embeddings
                </button>
                <button class="sub-tab-button" data-content-id="tabEmbeddingsAdmin" data-load-group="embeddings" role="tab">
                    Admin Tools
                </button>
                <button class="sub-tab-button" data-content-id="tabEmbeddingsDLQ" data-load-group="embeddings" role="tab">
                    DLQ
                </button>
                <button class="sub-tab-button" data-content-id="tabVectorStores" data-load-group="vector_stores" role="tab">
                    Vector Stores
                </button>
                <button class="sub-tab-button" data-content-id="tabVectorBatches" data-load-group="vector_stores" role="tab">
                    Vector Batches
                </button>
            </div>
        </div>

        <div id="research-subtabs" class="sub-tab-row" role="navigation" aria-label="Research sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabResearchArxiv" data-load-group="research" role="tab">
                    arXiv Search
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchSemantic" data-load-group="research" role="tab">
                    Semantic Scholar
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchBioRxiv" data-load-group="research" role="tab">
                    BioRxiv/MedRxiv
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchACM" data-load-group="research" role="tab">
                    ACM (OpenAlex)
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchWiley" data-load-group="research" role="tab">
                    Wiley (OpenAlex)
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchIEEE" data-load-group="research" role="tab">
                    IEEE Xplore
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchSpringer" data-load-group="research" role="tab">
                    Springer
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchScopus" data-load-group="research" role="tab">
                    Scopus
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchOAIngest" data-load-group="research" role="tab">
                    OA Ingest (DOI)
                </button>
                <button class="sub-tab-button" data-content-id="tabResearchChemRxiv" data-load-group="research" role="tab">
                    ChemRxiv
                </button>
            </div>
        </div>

        <div id="audio-subtabs" class="sub-tab-row" role="navigation" aria-label="Audio sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabAudioTTS" data-load-group="audio" role="tab">
                    Text to Speech
                </button>
                <button class="sub-tab-button" data-content-id="tabAudioStreaming" data-load-group="audio" role="tab">
                    Streaming Transcription
                </button>
                <button class="sub-tab-button" data-content-id="tabAudioFileTranscription" data-load-group="audio" role="tab">
                    File Transcription
                </button>
                <button class="sub-tab-button" data-content-id="tabTranscriptSeg" data-load-group="audio" role="tab">
                    Transcript Segmentation
                </button>
            </div>
        </div>

        <div id="admin-subtabs" class="sub-tab-row" role="navigation" aria-label="Admin sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabAdminUsers" data-load-group="admin" role="tab">
                    User Management
                </button>
                <button class="sub-tab-button" data-content-id="tabAccessControl" data-load-group="admin" role="tab">
                    Access Control
                </button>
                <button class="sub-tab-button" data-content-id="tabAdminUserPermissions" data-load-group="admin" role="tab">
                    User Permissions
                </button>
                <button class="sub-tab-button" data-content-id="tabAdminSystem" data-load-group="admin" role="tab">
                    System Status
                </button>
                <button class="sub-tab-button" data-content-id="tabModeration" data-load-group="admin" role="tab">
                    Moderation
                </button>
                <button class="sub-tab-button" data-content-id="tabMonitoring" data-load-group="admin" role="tab">
                    Monitoring
                </button>
                <button class="sub-tab-button" data-content-id="tabAdminJobs" data-load-group="jobs" role="tab">
                    Jobs
                </button>
                <button class="sub-tab-button" data-content-id="tabClaims" data-load-group="maintenance" role="tab">
                    Claims ⚖️
                </button>
            </div>
        </div>

        <div id="llm-subtabs" class="sub-tab-row" role="navigation" aria-label="LLM sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabLLMProviders" data-load-group="llm_providers" role="tab">
                    Providers
                </button>
                <button class="sub-tab-button" data-content-id="tabLLMDiagnostics" data-load-group="llm_diagnostics" role="tab">
                    Diagnostics
                </button>
            </div>
        </div>

        <div id="config-subtabs" class="sub-tab-row" role="navigation" aria-label="Config sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabConfigInfo" data-load-group="config_info" role="tab">
                    Configuration Info
                </button>
            </div>
        </div>

        <div id="sync-subtabs" class="sub-tab-row" role="navigation" aria-label="Sync sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabSyncSend" data-load-group="sync" role="tab">
                    Send Changes
                </button>
                <button class="sub-tab-button" data-content-id="tabSyncReceive" data-load-group="sync" role="tab">
                    Receive Changes
                </button>
            </div>
        </div>

        <div id="health-subtabs" class="sub-tab-row" role="navigation" aria-label="Health sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabHealthDashboard" data-load-group="health" role="tab">
                    Dashboard
                </button>
                <button class="sub-tab-button" data-content-id="tabHealthDetails" data-load-group="health" role="tab">
                    Individual Checks
                </button>
            </div>
        </div>

        <div id="mcp-subtabs" class="sub-tab-row" role="navigation" aria-label="MCP sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabMCPAuth" data-load-group="mcp" role="tab">
                    Authentication
                </button>
                <button class="sub-tab-button" data-content-id="tabMCPStatus" data-load-group="mcp" role="tab">
                    Status
                </button>
                <button class="sub-tab-button" data-content-id="tabMCPTools" data-load-group="mcp" role="tab">
                    Tools
                </button>
                <button class="sub-tab-button" data-content-id="tabMCPContexts" data-load-group="mcp" role="tab">
                    Contexts
                </button>
                <button class="sub-tab-button" data-content-id="tabMCPHealth" data-load-group="mcp" role="tab">
                    Health
                </button>
            </div>
        </div>

        <div id="llamacpp-subtabs" class="sub-tab-row" role="navigation" aria-label="Llama.cpp sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabLlamaCppStatus" data-load-group="llamacpp" role="tab">
                    Status
                </button>
                <button class="sub-tab-button" data-content-id="tabLlamaCppModels" data-load-group="llamacpp" role="tab">
                    Models
                </button>
                <button class="sub-tab-button" data-content-id="tabLlamaCppServer" data-load-group="llamacpp" role="tab">
                    Server Management
                </button>
                <button class="sub-tab-button" data-content-id="tabLlamaCppInference" data-load-group="llamacpp" role="tab">
                    Inference
                </button>
                <button class="sub-tab-button" data-content-id="tabLlamaCppReranking" data-load-group="llamacpp" role="tab">
                    Reranking
                </button>
            </div>
        </div>

        <div id="webscraping-subtabs" class="sub-tab-row" role="navigation" aria-label="Web Scraping sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabWebScrapingIngest" data-load-group="webscraping" role="tab">
                    Ingest
                </button>
                <button class="sub-tab-button" data-content-id="tabWebScrapingStatus" data-load-group="webscraping" role="tab">
                    Status
                </button>
                <button class="sub-tab-button" data-content-id="tabWebScrapingJobs" data-load-group="webscraping" role="tab">
                    Jobs
                </button>
                <button class="sub-tab-button" data-content-id="tabWebScrapingService" data-load-group="webscraping" role="tab">
                    Service
                </button>
                <button class="sub-tab-button" data-content-id="tabWebScrapingCookies" data-load-group="webscraping" role="tab">
                    Cookies
                </button>
                <button class="sub-tab-button" data-content-id="tabWebScrapingDuplicates" data-load-group="webscraping" role="tab">
                    Duplicates
                </button>
            </div>
        </div>

        <div id="maintenance-subtabs" class="sub-tab-row" role="navigation" aria-label="Maintenance sub-navigation">
            <div class="sub-tab-buttons" role="tablist">
                <button class="sub-tab-button" data-content-id="tabMaintenanceBatch" data-load-group="maintenance" role="tab">
                    Batch Operations
                </button>
                <button class="sub-tab-button" data-content-id="tabMaintenanceCleanup" data-load-group="maintenance" role="tab">
                    Database Cleanup
                </button>
                <button class="sub-tab-button" data-content-id="tabMaintenanceExportImport" data-load-group="maintenance" role="tab">
                    Export/Import
                </button>
                <button class="sub-tab-button" data-content-id="tabMaintenanceBackup" data-load-group="maintenance" role="tab">
                    Backup/Restore
                </button>
                <button class="sub-tab-button" data-content-id="tabClaims" data-load-group="maintenance" role="tab">
                    Claims
                </button>
            </div>
        </div>

        <!-- Main Content Area -->
        <main class="content-container" id="main-content-area" role="main">
            <!-- Global Settings Tab Content (always present) -->
            <div id="tabGlobalSettings" class="tab-content" role="tabpanel">
                <div class="endpoint-section">
                    <h2>
                        <span class="endpoint-method get">CONFIG</span>
                        <span class="endpoint-path">Global API Configuration</span>
                    </h2>

                    <div class="columns">
                        <div class="column">
                            <div class="form-group">
                                <label for="baseUrl">API Base URL:</label>
                                <div class="input-with-action">
                                    <input
                                        type="url"
                                        id="baseUrl"
                                        value="http://localhost:8000"
                                        placeholder="http://localhost:8000"
                                        aria-describedby="baseUrl-help"
                                    >
                                    <button id="copyBaseUrlBtn" type="button" class="btn btn-secondary btn-sm" title="Copy base URL">Copy</button>
                                </div>
                                <small id="baseUrl-help">The base URL for all API requests</small>
                            </div>
                        </div>

                        <div class="column">
                            <div class="form-group">
                                <label for="apiKeyInput">API Token: <span title="In single-user mode, the token is auto-configured by the server and the field will display '(Auto-configured)'. In multi-user mode, enter a Bearer token or enable 'Prefer X-API-KEY' to use API keys.">ⓘ</span></label>
                                <div class="input-with-action">
                                    <input
                                        type="password"
                                        id="apiKeyInput"
                                        value=""
                                        placeholder="Enter your API token"
                                        aria-describedby="apiKey-help"
                                    >
                                    <button id="toggleApiKeyVisibility" type="button" class="btn btn-secondary btn-sm" title="Show/Hide token">Show</button>
                                    <button id="copyApiKeyBtn" type="button" class="btn btn-secondary btn-sm" title="Copy API token">Copy</button>
                                </div>
                        <small id="apiKey-help">Auth headers: single-user uses 'X-API-KEY'; multi-user uses 'Authorization: Bearer' (or 'X-API-KEY' if preferred). Contact your administrator for an API token.</small>
                    </div>
                </div>
            </div>

            <div class="columns">
                <div class="column">
                    <div class="form-group">
                        <label>
                            <input type="checkbox" id="preferApiKeyInMultiUser" />
                            Prefer X-API-KEY header in multi-user mode (SQLite)
                        </label>
                        <small>When enabled, the WebUI sends X-API-KEY instead of Bearer in multi-user mode when supported.</small>
                    </div>
                </div>
                <div class="column">
                    <div class="form-group">
                        <label>
                            <input type="checkbox" id="includeTokenInCurl" />
                            Include auth token in generated cURL commands
                        </label>
                        <small>When disabled (default), cURL masks tokens as [REDACTED].</small>
                    </div>
                </div>
            </div>

            <div class="form-group">
                <div class="help-inline" style="font-size: 0.9em; color: var(--color-text-muted);">
                    Extensions streaming tip: if a browser extension calls the API (including text/event-stream), add its origin to ALLOWED_ORIGINS. See the CORS guidance.
                    <a href="/webui/CORS-SOLUTION.md#browser-extensions--streaming" target="_blank" rel="noopener">Read CORS & Extensions</a>
                </div>
            </div>

                    <div class="form-group mt-3">
                        <h3>Quick Actions</h3>
                        <div class="btn-group">
                            <button class="btn btn-primary" id="btnTestConnection">
                                Test Connection
                            </button>
                            <button class="btn btn-secondary" id="btnViewHistory">
                                View History
                            </button>
                            <button class="btn btn-secondary" id="btnRefreshPage">
                                Refresh Page
                            </button>
                        </div>
                    </div>

                    <div class="form-group mt-3">
                        <h3>Keyboard Shortcuts</h3>
                        <div class="text-small text-muted">
                            <p><kbd>Ctrl/Cmd + K</kbd> - Search endpoints</p>
                            <p><kbd>Ctrl/Cmd + Shift + D</kbd> - Toggle dark mode</p>
                            <p><kbd>Ctrl/Cmd + Shift + H</kbd> - Show request history</p>
                            <p><kbd>Escape</kbd> - Close modals</p>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Request History Tab -->
            <div id="tabHistory" class="tab-content" role="tabpanel">
                <div class="endpoint-section">
                    <h2>Request History</h2>
                    <div id="history-container">
                        <p class="text-muted">Request history will appear here...</p>
                    </div>
                </div>
            </div>

            <!-- Simple Landing (Quick Actions) -->
            <div id="tabSimpleLanding" class="tab-content" role="tabpanel">
                <div class="endpoint-section">
                    <h2>Quick Actions</h2>
                    <p class="text-muted">A streamlined panel for common tasks. Toggle "Show Advanced Panels" in the header to access full controls.</p>
                </div>
                <div class="endpoint-section" id="simpleChat">
                    <div class="collapsible-header" data-collapsible="simpleChat">
                        <div>
                            <h3>Chat Assistant</h3>
                            <p class="text-muted" style="margin:4px 0 0;">Full chat experience from the Chat tab, pinned here for quick access.</p>
                        </div>
                        <button class="btn btn-sm btn-secondary collapsible-toggle-btn" type="button" data-target="simpleChat">Hide</button>
                    </div>
                    <div class="collapsible-body" id="simpleChat_body">
                        <div id="simpleChatPortal" data-chat-host="simple">
                            <div class="chat-host-placeholder text-muted" data-chat-placeholder>
                                Loading chat interface…
                            </div>
                        </div>
                    </div>
                </div>
                <div class="columns">
                    <!-- Ingest File/URL -->
                    <div class="column">
                        <div class="endpoint-section" id="simpleIngest">
                            <div class="collapsible-header" data-collapsible="simpleIngest">
                                <h3>Ingest File or URL</h3>
                                <button class="btn btn-sm btn-secondary collapsible-toggle-btn" type="button" data-target="simpleIngest">Hide</button>
                            </div>
                            <div class="collapsible-body" id="simpleIngest_body">
                            <div class="form-group">
                                <label for="simpleIngest_media_type">Media Type</label>
                                <select id="simpleIngest_media_type">
                                    <option value="document">Document</option>
                                    <option value="pdf">PDF</option>
                                    <option value="video">Video</option>
                                    <option value="audio">Audio</option>
                                    <option value="ebook">eBook</option>
                                    <option value="web">Web (scrape)</option>
                                </select>
                            </div>
                            <div class="form-group" id="simpleIngest_url_group">
                                <label for="simpleIngest_url">URL</label>
                                <div style="display:flex; gap:8px; align-items:center;">
                                    <input type="url" id="simpleIngest_url" placeholder="https://example.com/article-or-media" style="flex:1;">
                                    <button class="btn btn-secondary btn-sm" id="simpleIngest_paste_url" title="Paste from clipboard">Paste</button>
                                </div>
                            </div>
                            <div class="form-group" id="simpleIngest_file_group">
                                <label for="simpleIngest_file">File</label>
                                <input type="file" id="simpleIngest_file" multiple aria-describedby="simpleIngest_file_help">
                                <small id="simpleIngest_file_help">You can select multiple files. Media type auto-detected from extension.</small>
                            </div>
                            <div class="form-group">
                                <label for="simpleIngest_model">Analysis Model (optional)</label>
                                <select id="simpleIngest_model" class="llm-model-select">
                                    <option value="">Use default</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label for="simpleIngest_seed">Seed Prompt (optional)</label>
                                <textarea id="simpleIngest_seed" rows="2" placeholder="Give the analysis a goal or persona for better results"></textarea>
                            </div>
                            <div class="form-group">
                                <label for="simpleIngest_system">System Prompt (optional)</label>
                                <textarea id="simpleIngest_system" rows="2" placeholder="System instructions to guide analysis"></textarea>
                            </div>
                            <div class="form-group">
                                <label title="Run LLM analysis after ingestion (generates notes/summaries)"><input type="checkbox" id="simpleIngest_perform_analysis" checked aria-describedby="simpleIngest_perform_help"> Perform Analysis</label>
                                <label style="margin-left:12px;" title="Split long content into chunks for better retrieval"><input type="checkbox" id="simpleIngest_chunking" checked aria-describedby="simpleIngest_chunk_help"> Chunk Content</label>
                                <div class="text-muted text-small" style="margin-top:4px;">
                                    <span id="simpleIngest_perform_help">Optional: Enable to immediately analyze ingested content.</span>
                                    <span id="simpleIngest_chunk_help" style="margin-left:12px;">Recommended for large documents and videos.</span>
                                </div>
                            </div>
                            <!-- Web scraping options (visible when Media Type = Web) -->
                            <div id="simpleIngest_web_opts" style="display:none; border-top:1px dashed var(--color-border); padding-top:8px; margin-top:8px;">
                                <div class="form-group">
                                    <label for="simpleIngest_scrape_method">Scrape Method</label>
                                    <select id="simpleIngest_scrape_method" aria-describedby="simpleIngest_scrape_help" title="How links are traversed and processed">
                                        <option value="individual">Individual URLs</option>
                                        <option value="url_level">URL Level</option>
                                        <option value="recursive_scraping">Recursive Scraping</option>
                                    </select>
                                    <small id="simpleIngest_scrape_help">Choose how to follow links. URL Level limits traversal by path depth; Recursive walks links up to Max Depth/Pages.</small>
                                </div>
                                <div class="form-group" id="simpleIngest_web_url_group">
                                    <label for="simpleIngest_web_url">Start URL</label>
                                    <div style="display:flex; gap:8px; align-items:center;">
                                        <input type="url" id="simpleIngest_web_url" placeholder="https://example.com/" style="flex:1;">
                                        <button class="btn btn-secondary btn-sm" id="simpleIngest_paste_web_url" title="Paste from clipboard">Paste</button>
                                    </div>
                                </div>
                                <div class="form-group" id="simpleIngest_url_level_group" style="display:none;">
                                    <label for="simpleIngest_url_level">URL Level</label>
                                    <input type="number" id="simpleIngest_url_level" value="2" min="1">
                                </div>
                                <div class="columns" id="simpleIngest_recursive_group" style="display:none;">
                                    <div class="column">
                                        <div class="form-group">
                                            <label for="simpleIngest_max_pages">Max Pages</label>
                                            <input type="number" id="simpleIngest_max_pages" value="10" min="1">
                                        </div>
                                    </div>
                                    <div class="column">
                                        <div class="form-group">
                                            <label for="simpleIngest_max_depth">Max Depth</label>
                                            <input type="number" id="simpleIngest_max_depth" value="3" min="1">
                                        </div>
                                    </div>
                                </div>
                                <div class="columns">
                                    <div class="column">
                                        <div class="form-group">
                                            <label for="simpleIngest_crawl_strategy">Crawl Strategy</label>
                                            <select id="simpleIngest_crawl_strategy">
                                                <option value="">(default)</option>
                                                <option value="best_first">best_first</option>
                                            </select>
                                        </div>
                                    </div>
                                    <div class="column">
                                        <div class="form-group">
                                            <label>
                                                <input type="checkbox" id="simpleIngest_include_external"> Include external links
                                            </label>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="btn-group">
                                <button class="api-button" id="simpleIngest_submit" disabled>Ingest</button>
                                <button class="btn btn-secondary" id="simpleIngest_clear">Clear</button>
                                <button class="btn btn-secondary" id="simpleIngest_show_curl" title="Show cURL for this request">Show cURL</button>
                            </div>
                            <div id="simpleIngest_job" class="text-small" style="margin-top:8px; display:none;"></div>
                            <div id="simpleIngest_queue" class="text-small" aria-live="polite" style="margin-top:6px; display:none;"></div>
                            <h4>Response</h4>
                            <pre id="simpleIngest_response">---</pre>
                            <div id="simpleIngest_correlation" class="correlation-snippet" aria-live="polite" style="margin-top:6px; color: var(--color-text-muted); font-size: 0.85em;"></div>
                            <pre id="simpleIngest_curl" style="display:none;"></pre>
                            </div>
                        </div>
                    </div>
                    <!-- Search content -->
                    <div class="column">
                        <div class="endpoint-section" id="simpleSearch">
                            <div class="collapsible-header" data-collapsible="simpleSearch">
                                <h3>Search Content</h3>
                                <button class="btn btn-sm btn-secondary collapsible-toggle-btn" type="button" data-target="simpleSearch">Hide</button>
                            </div>
                            <div class="collapsible-body" id="simpleSearch_body">
                            <div class="form-group">
                                <label for="simpleSearch_q">Query</label>
                                <div style="display:flex; gap:8px; align-items:center;">
                                    <input type="text" id="simpleSearch_q" placeholder="Keywords or phrase" style="flex:1;">
                                    <button class="btn btn-secondary btn-sm" id="simpleSearch_clear" title="Clear">Clear</button>
                                </div>
                            </div>
                            <div class="columns" style="align-items:flex-end; gap:12px;">
                                <div class="column">
                                    <div class="form-group">
                                        <label for="simpleSearch_rpp">Results per page</label>
                                        <input type="number" id="simpleSearch_rpp" value="10" min="1" max="100">
                                    </div>
                                </div>
                                <div class="column">
                                    <div class="form-group">
                                        <div class="btn-group">
                                            <button class="btn btn-secondary" id="simpleSearch_prev" disabled>Prev</button>
                                            <button class="btn btn-secondary" id="simpleSearch_next" disabled>Next</button>
                                        </div>
                                    </div>
                                </div>
                                <div class="column">
                                    <div id="simpleSearch_pageinfo" class="text-muted" style="min-width:140px; text-align:right;"></div>
                                </div>
                            </div>
                            <div class="btn-group">
                                <button class="api-button" id="simpleSearch_run" disabled>Search</button>
                                <button class="btn btn-secondary" id="simpleSearch_show_curl" title="Show cURL for this request">Show cURL</button>
                            </div>
                            <div id="simpleSearch_results" style="margin-top:8px;"></div>
                            <pre id="simpleSearch_curl" style="display:none;"></pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- No search results message -->
            <div id="no-search-results">
                <p>No endpoints match your search.</p>
            </div>

            <!-- Other tab contents will be loaded here dynamically -->
        </main>
    </div>

    <!-- Load JavaScript files -->
    <script src="js/utils.js"></script>
    <script src="js/sanitizer.js"></script>
    <script src="js/safe-dom.js"></script>
    <script src="js/components.js"></script>
    <script src="js/api-client.js"></script>
    <script src="js/endpoint-helper.js"></script>
    <script src="js/tab-functions.js"></script> <!-- Keep legacy functions while migrating handlers -->
    <script src="js/legacy-helpers.js"></script>
    <script src="js/module-loader.js"></script>
    <script src="js/personalization.js"></script>
    <script src="js/shared-chat-portal.js"></script>
    <script src="js/metrics.js"></script>
    <script src="js/main.js"></script>
</body>
</html>
